package com.liveinstars.im.core.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.liveinstars.api.dto.BatchImGetUserReq;
import com.liveinstars.api.dto.ImGetUserInfo;
import com.liveinstars.api.facade.BadWordsApi;
import com.liveinstars.api.facade.ImUserCentreApi;
import com.liveinstars.im.common.dto.ChatGroupDTO;
import com.liveinstars.im.common.enums.IMExceptionEnum;
import com.liveinstars.im.common.enums.SpecialUserEnum;
import com.liveinstars.im.domain.dao.model.ChatGroup;
import com.liveinstars.im.domain.dao.model.ChatGroupMember;
import com.liveinstars.im.domain.dao.model.MessageGroup;
import com.liveinstars.im.domain.manager.ChatGroupManager;
import com.liveinstars.im.domain.manager.ChatGroupMemberManager;
import com.liveinstars.im.domain.manager.MessageGroupManager;
import com.liveinstars.im.entity.ChatMessage;
import com.liveinstars.api.im.query.ChatGroupQuery;
import com.liveinstars.api.im.vo.ChatGroupDetailVO;
import com.liveinstars.api.im.vo.ChatGroupRecordVO;
import com.liveinstars.api.im.vo.ChatMsgVO;
import com.liveinstars.api.im.vo.UserVO;
import com.onepiece.cache.service.CacheService;
import com.liveinstars.im.api.MsgGeneratorService;
import com.liveinstars.im.api.NotifyData;
import com.liveinstars.im.common.enums.ChatGroupTypeEnum;
import com.liveinstars.im.common.exception.IMRuntimeException;
import com.liveinstars.im.core.service.ChatGroupService;
import com.onepiece.shipelves.common.Result;
import com.onepiece.shipelves.common.utils.CacheUtil;
import com.onepiece.shipelves.common.vo.Page;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author: ting
 * @date: 2020/3/3
 */
@Service("chatGroupService")
public class ChatGroupServiceImpl implements ChatGroupService {

    private final static Logger logger = LoggerFactory.getLogger(ChatGroupServiceImpl.class);

    @Autowired
    private ChatGroupManager chatGroupManager;

    @Autowired
    private MsgGeneratorService msgGeneratorService;

    @Autowired
    private MessageGroupManager messageGroupManager;

    @Autowired
    private ChatGroupMemberManager chatGroupMemberManager;

    @Autowired
    private ImUserCentreApi imUserCentreApi;

    @Autowired
    private BadWordsApi badWordsApi;

    @Autowired
    CacheService cache;

    @Override
    public Page<ChatGroupRecordVO> pageBackendRecordByQuery(ChatGroupQuery query) {

        //圈子查询
        query.setGroupType(ChatGroupTypeEnum.CHAT_CIRCLE.getValue());
        if (query.getHidden() == null) {
            query.setHidden(false);
        }
        IPage<ChatGroup> iPage = chatGroupManager.pageByQuery(query);
        List<ChatGroupRecordVO> list = Lists.newArrayList();
        List<Long> groupIdList = Lists.newArrayList();
        List<ChatGroupDTO> groupDTOList = Lists.newArrayList();
        Set<Long> userIdList = Sets.newHashSet();

        //获取额外查询数据
        if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
            for (ChatGroup chatGroup : iPage.getRecords()) {
                groupIdList.add(chatGroup.getId());
                userIdList.add(chatGroup.getCreateById());
                groupDTOList.add(new ChatGroupDTO(chatGroup));
            }
            //获取圈子人数
            Map<Long, Integer> countMap = chatGroupMemberManager.mapMemberCountByChatGroupIdList(groupIdList);

            //获取圈子创建人信息
            BatchImGetUserReq batchImGetUserReq = new BatchImGetUserReq();
            batchImGetUserReq.setUids(new ArrayList<>(userIdList));
            Result<List<ImGetUserInfo>> userInfoListResult = imUserCentreApi.batchImGetUserInfo(batchImGetUserReq);
            Map<Long, String> userNameMap = Maps.newHashMap();
            if (userInfoListResult.getCode().equals(Result.SUCCESS)) {
                List<ImGetUserInfo> userInfoList = userInfoListResult.getData();
                userInfoList.forEach(user -> userNameMap.put(user.getUid(), user.getUserName()));
            } else {
                throw new RuntimeException(userInfoListResult.getMessage());
            }

            //数据拼装
            list = groupDTOList.stream().map(dto -> {
                ChatGroupRecordVO vo = dto.chatGroupTransToChatGroupRecordVO();
                if (countMap.containsKey(vo.getId())) {
                    vo.setUserCount(countMap.get(vo.getId()));
                }
                if (userNameMap.containsKey(vo.getCreateUserId())) {
                    vo.setCreateUserName(userNameMap.get(vo.getCreateUserId()));
                }
                return vo;
            }).collect(Collectors.toList());
        }
        Page<ChatGroupRecordVO> page = new Page<ChatGroupRecordVO>(list,
                Long.valueOf(iPage.getCurrent()).intValue(),
                Long.valueOf(iPage.getSize()).intValue(),
                Long.valueOf(iPage.getTotal()).intValue());
        return page;
    }

    @Override
    public Page<ChatGroupRecordVO> pageByQuery(ChatGroupQuery query) {
        List<Long> chatGroupIdList = chatGroupMemberManager.listChatGroupIdByUserIdAndGroupType(query.getUserId(), ChatGroupTypeEnum.CHAT_CIRCLE.getValue());
        query.setHidden(true);
        Page<ChatGroupRecordVO> page = this.pageBackendRecordByQuery(query);
        page.getList().stream().forEach(record -> {
            if (chatGroupIdList.contains(record.getId())) {
                record.setMeIn(true);
            }else {
                record.setMeIn(false);
            }
        });
        return page;
    }

    @Override
    public ChatGroupDetailVO getDetailById(Long id) {
        ChatGroup chatGroup = chatGroupManager.getById(id);
        ChatGroupDTO dto = new ChatGroupDTO(chatGroup);
        ChatGroupDetailVO vo = dto.chatGroupTransToChatGroupDetailVO();
        return vo;
    }

    @Override
    public ChatGroupDetailVO getDetailWithManagerById(Long id) {
        ChatGroup chatGroup = chatGroupManager.getById(id);
        ChatGroupDTO dto = new ChatGroupDTO(chatGroup);
        ChatGroupDetailVO vo = dto.chatGroupTransToChatGroupDetailVO();
        List<Long> userIdList = new ArrayList<>();
        if (chatGroup.getCreateById() != null) {
            userIdList.add(chatGroup.getCreateById());
        }
        if (chatGroup.getManager1Id() != null) {
            userIdList.add(chatGroup.getManager1Id());
        }
        if (chatGroup.getManager2Id() != null) {
            userIdList.add(chatGroup.getManager2Id());
        }
        BatchImGetUserReq req = new BatchImGetUserReq();
        req.setUids(userIdList);
        if (CollectionUtils.isNotEmpty(userIdList)) {
            Result<List<ImGetUserInfo>> listResult = imUserCentreApi.batchImGetUserInfo(req);
            if (listResult.getCode().equals(Result.SUCCESS)) {
                listResult.getData().forEach(userInfo -> {
                    UserVO userVO = new UserVO();
                    userVO.setId(userInfo.getUid());
                    userVO.setName(userInfo.getUserName());
                    userVO.setNickName(userInfo.getNickName());
                    userVO.setIndividualResume(userInfo.getIndividualResume());
                    userVO.setDate(userInfo.getRegdate().toString());
                    userVO.setGroupId(userInfo.getGroupId());
                    userVO.setLogo(userInfo.getLogo());
                    //userVO.setMobile(userInfo.getMobile());
                    if (chatGroup.getCreateById() != null
                            && chatGroup.getCreateById().equals(userInfo.getUid())) {
                        vo.setCreateBy(userVO);
                    }
                    if (chatGroup.getManager1Id() != null
                            && chatGroup.getManager1Id().equals(userInfo.getUid())) {
                        vo.setManager1(userVO);
                    }
                    if (chatGroup.getManager2Id() != null
                            && chatGroup.getManager2Id().equals(userInfo.getUid())) {
                        vo.setManager2(userVO);
                    }
                });
            } else {
                logger.error("获取用户信息异常: {}", listResult.getMessage());
            }
        }
        return vo;
    }

    @Override
    public void updateById(ChatGroupDetailVO vo) {
        if (vo.getId() == null || vo.getId().equals(0L)) {
            return;
        }
        ChatGroupDTO dto = new ChatGroupDTO(vo);
        chatGroupManager.updateById(dto.getChatGroup());
    }

    @Override
    public void updateHotById(Long id, Integer hot) {
        ChatGroup chatGroup = new ChatGroup();
        chatGroup.setId(id);
        chatGroup.setHot(hot);
        chatGroupManager.updateById(chatGroup);
    }

    @Override
    public Page<ChatMsgVO> pageChatMsgByChatGroupId(Long id, Integer pageSize, Integer pageNum) {
        List<ChatMsgVO> list = Lists.newArrayList();
        IPage<MessageGroup> iPage = messageGroupManager.pageByChatGroupId(id, pageNum, pageSize);
        if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
            Set<Long> userIdList = Sets.newHashSet();
            Set<Long> chatGroupIdList = Sets.newHashSet();
            for (MessageGroup message : iPage.getRecords()) {
                userIdList.add(message.getFromId());
                chatGroupIdList.add(message.getChatGroupId());
                ChatMsgVO vo = new ChatMsgVO();
                vo.setId(message.getId());
                vo.setGroupId(message.getChatGroupId());
                vo.setCreateTime(Long.valueOf(message.getDate()));
                vo.setFromId(message.getFromId());
                //vo.setFromName();
                vo.setToId(message.getChatGroupId());
                vo.setContentType(message.getContentType());
                //vo.setToName();
                if (message.getContentType().equals(ChatMessage.CONTENT_TYPE_NORMAL)) {
                    vo.setContent(message.getContent());
                } else if (message.getContentType().equals(ChatMessage.CONTENT_TYPE_ATTACHMENT)) {
                    vo.setContent(message.getPath());
                }
                list.add(vo);
            }
            Map<Long, String> userNameMap = Maps.newHashMap();
            Map<Long, String> chatGroupNameMap = Maps.newHashMap();
            List<ChatGroup> chatGroupList = chatGroupManager.listByIds(chatGroupIdList);
            chatGroupList.forEach(chatGroup -> chatGroupNameMap.put(chatGroup.getId(), chatGroup.getName()));
            BatchImGetUserReq req = new BatchImGetUserReq();
            req.setUids(new ArrayList<>(userIdList));
            Result<List<ImGetUserInfo>> userInfoListResult = imUserCentreApi.batchImGetUserInfo(req);
            if (userInfoListResult.getCode().equals(Result.SUCCESS)) {
                List<ImGetUserInfo> userInfoList = userInfoListResult.getData();
                userInfoList.forEach(user -> userNameMap.put(user.getUid(), user.getUserName()));
            } else {
                logger.error("用户中心查询异常：userIdList:{}", userIdList.toString());
            }
            list.forEach(chatMsgVO -> {
                if (userNameMap.containsKey(chatMsgVO.getFromId())) {
                    chatMsgVO.setFromName(userNameMap.get(chatMsgVO.getFromId()));
                }
                if (chatGroupNameMap.containsKey(chatMsgVO.getToId())) {
                    chatMsgVO.setToName(chatGroupNameMap.get(chatMsgVO.getToId()));
                }
            });
        }
        Page<ChatMsgVO> page = new Page<>(list,
                Long.valueOf(iPage.getCurrent()).intValue(),
                Long.valueOf(iPage.getSize()).intValue(),
                Long.valueOf(iPage.getTotal()).intValue());

        return page;
    }

    @Override
    public void deleteByChatGroupIdAndMsgId(Long chatGroupId, Long msgId) {
        messageGroupManager.deleteByChatGroupIdAndMsgId(chatGroupId, msgId);
        List<ChatGroupMember> memberList = chatGroupMemberManager.listMemberByChatGroupId(chatGroupId);
        for (ChatGroupMember member : memberList) {
            removeUnreadMessage(member.getUserId(), msgId);
        }
    }

    @Override
    public void removeUnreadMessage(Long userId, Long msgId) {
        cache.zremrangebyscore(CacheUtil.getIMUserMessageList(userId), msgId, msgId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disbandChatGroupByBackend(Long groupId) {
        ChatGroup chatGroup = chatGroupManager.getById(groupId);
        msgGeneratorService.sendNotifyMessage(new NotifyData(SpecialUserEnum.IM_ASSISTANT.getId(), 0L, chatGroup.getName() + "已解散！", chatGroup.getId()));
        chatGroupMemberManager.deleteMemberByChatGroupId(groupId);
        chatGroupManager.deleteById(groupId);
    }

    @Override
    public List<ChatGroupRecordVO> listChatGroupByCreateUserId(Long userId) {
        List<ChatGroup> chatGroupList = chatGroupManager.listByCreateUserId(userId);
        List<ChatGroupRecordVO> list = chatGroupList.stream().map(chatGroup -> new ChatGroupDTO(chatGroup).chatGroupTransToChatGroupRecordVO())
                .collect(Collectors.toList());
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createChatGroupWithMember(ChatGroupDTO chatGroupDTO) {
        int time = Long.valueOf(System.currentTimeMillis()/1000).intValue();
        chatGroupDTO.getChatGroup().setCreateDate(time);
        chatGroupManager.save(chatGroupDTO.getChatGroup());
        if (CollectionUtils.isNotEmpty(chatGroupDTO.getMemberList())) {
            chatGroupDTO.getMemberList().forEach(member -> member.setChatGroupId(chatGroupDTO.getChatGroup().getId()));
            chatGroupMemberManager.saveBatch(chatGroupDTO.getMemberList());
        }
    }

    @Override
    public ChatGroup getFriendsChatGroup(Long userIdA, Long userIdB) {
        ChatGroup friendsChatGroup = chatGroupManager.getFriendsChatGroup(userIdA, userIdB);
        return friendsChatGroup;
    }

    @Override
    public void addSpecialChatGroup(Long userId, SpecialUserEnum specialUserEnum) {
        ImGetUserInfo userInfo = imUserCentreApi.imGetUserInfo(userId);
        ChatGroup chatGroup = chatGroupManager.createFriendsChatGroup(userId, (long) specialUserEnum.getId());
        List<ChatGroupMember> memberList = Lists.newArrayList();
        ChatGroupMember chatGroupMember = new ChatGroupMember();
        chatGroupMember.setRemarkName(specialUserEnum.getName());
        chatGroupMember.setUserId(specialUserEnum.getId());
        chatGroupMember.setGroupType(chatGroup.getGroupType());
        chatGroupMember.setChatGroupId(chatGroup.getId());
        memberList.add(chatGroupMember);
        chatGroupMember = new ChatGroupMember();
        chatGroupMember.setUserId(userId);
        chatGroupMember.setGroupType(chatGroup.getGroupType());
        chatGroupMember.setChatGroupId(chatGroup.getId());
        memberList.add(chatGroupMember);
        chatGroupMemberManager.batchSaveFriendMember(memberList, chatGroup.getId());
    }

    @Override
    public void updateMemberRemarkName(Long selfId, Long chatGroupId, String remarkName) {
        if (StringUtils.isNotEmpty(remarkName)){
            if (badWordsApi.hasBadWords(remarkName, false)) {
                throw new IMRuntimeException(IMExceptionEnum.BAD_WORDS_ERROR);
            }
        }
        ChatGroupMember chatGroupMember = new ChatGroupMember();
        chatGroupMember.setRemarkName(remarkName);
        chatGroupMemberManager.updateByUserIdAndChatGroupId(chatGroupMember, selfId, chatGroupId);
    }

    @Override
    public List<ChatGroupRecordVO> listChatGroupByCreateUserIdAndInterestId(Long userId, Integer interestId) {
        List<ChatGroup> chatGroupList = chatGroupManager.listByCreateUserIdAndInterestId(userId, interestId);
        List<ChatGroupRecordVO> list = chatGroupList.stream().map(chatGroup -> new ChatGroupDTO(chatGroup).chatGroupTransToChatGroupRecordVO())
                .collect(Collectors.toList());
        return list;
    }

    @Override
    public ChatGroupRecordVO getChatGroupByCreateUserIdAndInterestId(Long userId, Integer interestId) {
        List<ChatGroup> chatGroupList = chatGroupManager.listByCreateUserIdAndInterestId(userId, interestId);
        List<ChatGroupRecordVO> list = chatGroupList.stream().map(chatGroup -> new ChatGroupDTO(chatGroup).chatGroupTransToChatGroupRecordVO())
                .collect(Collectors.toList());
        return list.size() > 0 ? list.get(0) : null;
    }
}
